#    GMail-Notifier - A cooler looking gmail notifier for Ubuntu
#    Copyright (C) 2009 Uday K Verma
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import gtk, gobject
import gmailnotifier.config as config
import gmailnotifier.apppaths as apppaths


class StatusIconManager(gobject.GObject):
    
    __gsignals__ = {
        'request-refresh' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()),
        'request-prefs' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()),
        'request-inbox' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()),
        'request-mail' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)),
        'request-compose' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()),
        'request-notification-disable' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN,)),
        'request-quit' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()),
        'request-activate' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()),
    }
    
    def __init__(self, update_checker = None):
        gobject.GObject.__init__(self)
        
        self.create_icons ()
        
        self.statusicon = gtk.StatusIcon ()
        self.update_checker = update_checker
        
        self.statusicon.set_from_file (self.icon_path)
        self.statusicon.set_visible (True)
        self.statusicon.connect ('popup-menu', self.on_popup_menu)
        self.statusicon.connect ('activate', self.on_activate)
        self.menu = None
        self.menuToMail = {}
        self.setDefaultMenu ()
        
    def create_icons(self):
        self.icon_path = os.path.join (apppaths.media_path(), "images/gmail-icon32.png")
        self.gray_icon_path = os.path.join (apppaths.media_path(), "images/gray-gmail32.png")
        
    def on_popup_menu (self, status_icon, button, activate_time):
        if self.menu:
            self.menu.popup (None, None, gtk.status_icon_position_menu, button, activate_time, status_icon)
            
    def on_activate (self, status_icon):
        self.emit ('request-activate')
        
    def updateForMessages (self, messages):
        self.statusicon.set_tooltip ("%d new messages" % (len(messages)))
        self.updateIcon (messages)
        self.updateMenu (messages)
        
    def updateIcon (self, messages):
        if messages:
            self.statusicon.set_from_file (self.icon_path)
        else:
            self.statusicon.set_from_file (self.gray_icon_path)
        
    def on_refresh (self, m):
        if self.refresh_cb:
            self.refresh_cb ()
            
    def _makeMenuItem (self, mi, cb):
        mi.connect ('activate', cb)
        return mi
    
    def on_disable_notifications (self, sender):
        self.emit ('request-notification-disable', sender.get_active())
            
    def setDefaultMenu (self):
        menu = gtk.Menu ()
        self.menuToMail.clear()
        
        self._checkAddUpdateItem (menu)
        
        menu.add (self._makeMenuItem (gtk.ImageMenuItem (gtk.STOCK_REFRESH),
                                      lambda x: self.emit ('request-refresh')))
        menu.add (self._makeMenuItem (gtk.MenuItem ("Go to Inbox ..."),
                                      lambda x: self.emit ('request-inbox')))
        menu.add (gtk.SeparatorMenuItem ())
        menu.add (self._makeMenuItem (gtk.MenuItem ("Preferences ..."),
                                      lambda x: self.emit ('request-prefs')))
        
        check_menu = gtk.CheckMenuItem ("Disable all notifications")
        
        menu.add (gtk.SeparatorMenuItem ())
        menu.add (self._makeMenuItem (gtk.MenuItem ("Quit"), lambda x: self.emit ('request-quit')))
        menu.show_all()
        
        self.menu = menu
        
    def on_mail_item(self, sender):
        if self.menuToMail.has_key (sender):
            self.emit ('request-mail', self.menuToMail [sender])
        
    def _makeMailMenuItem (self, title, link):
        m = gtk.MenuItem (title)
        self.menuToMail [m] = link
        m.connect ('activate', self.on_mail_item)
        
        return m
    
    def _checkAddUpdateItem (self, menu):
        if self.update_checker.isUpdateAvailable ():
            text, url = self.update_checker.getMenuItemDetails ()
            
            #cheating! :D, seriously though, the mail notification should just be url-request or something
            #
            menu.add (self._makeMailMenuItem (text, url))
            menu.add (gtk.SeparatorMenuItem ())
    
    def _compact(self, str):
        if len(str) > 70:
            return str[0:67] + "..."
        return str
    
    def _check_subject (self, msg):
        if not msg:
            return '(no-subject)'
        return msg
    
    def updateForFailed (self):
        self.setDefaultMenu ()
            
    def updateMenu (self, messages):
        menu = gtk.Menu()
        self.menuToMail.clear()
        
        self._checkAddUpdateItem (menu)

        menu.add (self._makeMenuItem (gtk.ImageMenuItem (gtk.STOCK_REFRESH),
                                      lambda x: self.emit ('request-refresh')))
        menu.add (self._makeMenuItem (gtk.MenuItem ("Go to Inbox ..."),
                                      lambda x: self.emit ('request-inbox')))
        
        menu.add (gtk.SeparatorMenuItem ())
        if not messages:
            mi = gtk.MenuItem ("No Messages")
            mi.set_state (gtk.STATE_INSENSITIVE)
            menu.add (mi)
        else:
            # prepare the top 4 menu items
            for i in range (4):
                if i >= len(messages):
                    break
                
                menu.add (self._makeMailMenuItem (self._compact(self._check_subject (messages [i].title)), messages [i].link))
            
            # prepare
            if len(messages) > 4:
                mails_sub = gtk.Menu ()
                for i in range (4, 16):
                    if i >= len(messages):
                        break
                    mails_sub.add (self._makeMailMenuItem (self._compact(self._check_subject (messages [i].title)),
                                                       messages [i].link))
                if len(messages) > 16:
                    mails_sub.add (gtk.SeparatorMenuItem())
                    mails_sub.add (self._makeMenuItem (gtk.MenuItem ("View more messages"),
                                            lambda x: self.emit ('request-inbox')))
                mails_sub.show_all ()
                
                msm = gtk.MenuItem ("More messages")
                msm.set_submenu (mails_sub)
                menu.add (msm)
                
        menu.add (gtk.SeparatorMenuItem ())
        menu.add (self._makeMenuItem (gtk.MenuItem ("Preferences ..."),
                                      lambda x: self.emit ('request-prefs')))
        
        check_menu = gtk.CheckMenuItem ("Disable all notifications")
        is_disabled = int(config.get_config ("disable-notifications"))
        check_menu.set_active (is_disabled)
        check_menu.connect ('activate', self.on_disable_notifications)
        menu.add (check_menu)
        
        menu.add (gtk.SeparatorMenuItem ())
        menu.add (self._makeMenuItem (gtk.MenuItem ("Quit"), lambda x: self.emit ('request-quit')))
        menu.show_all()
        
        self.menu = menu

